using Engine;
using Engine.Graphics;

namespace Game
{
	public abstract class Camera
	{
		public GameWidget GameWidget { get; private set; }

		public VrEye? Eye { get; private set; }

		public abstract Vector3 ViewPosition { get; }

		public abstract Vector3 ViewDirection { get; }

		public abstract Vector3 ViewUp { get; }

		public abstract Vector3 ViewRight { get; }

		public abstract Matrix ViewMatrix { get; }

		public abstract Matrix InvertedViewMatrix { get; }

		public abstract Matrix ProjectionMatrix { get; }

		public abstract Matrix ScreenProjectionMatrix { get; }

		public abstract Matrix InvertedProjectionMatrix { get; }

		public abstract Matrix ViewProjectionMatrix { get; }

		public abstract Vector2 ViewportSize { get; }

		public abstract Matrix ViewportMatrix { get; }

		public abstract BoundingFrustum ViewFrustum { get; }

		public abstract bool UsesMovementControls { get; }

		public abstract bool IsEntityControlEnabled { get; }

		protected Camera(GameWidget gameWidget)
		{
			GameWidget = gameWidget;
		}

		public Vector3 WorldToScreen(Vector3 worldPoint, Matrix worldMatrix)
		{
			if (!Eye.HasValue)
			{
				return new Viewport(0, 0, Window.Size.X, Window.Size.Y).Project(worldPoint, ScreenProjectionMatrix, ViewMatrix, worldMatrix);
			}
			return new Viewport(0, 0, (int)ViewportSize.X, (int)ViewportSize.Y).Project(worldPoint, ScreenProjectionMatrix, ViewMatrix, worldMatrix);
		}

		public Vector3 ScreenToWorld(Vector3 screenPoint, Matrix worldMatrix)
		{
			if (!Eye.HasValue)
			{
				return new Viewport(0, 0, Window.Size.X, Window.Size.Y).Unproject(screenPoint, ScreenProjectionMatrix, ViewMatrix, worldMatrix);
			}
			return new Viewport(0, 0, (int)ViewportSize.X, (int)ViewportSize.Y).Unproject(screenPoint, ScreenProjectionMatrix, ViewMatrix, worldMatrix);
		}

		public virtual void Activate(Camera previousCamera)
		{
		}

		public abstract void Update(float dt);

		public virtual void PrepareForDrawing(VrEye? eye)
		{
			Eye = eye;
		}
	}
}
